package com.zys.zys_mybatis;

import com.zys.zys_mybatis.utils.StringUtil;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @BelongsProject: ZYSMybatis
 * @BelongsPackage: com.zys.zys_mybatis
 * @Author: ZYS
 * @CreateTime: 2024-05-29  18:32
 * @Description: TODO
 */
public class SqlExecuteHandler {
    private static Method method;
    private static Object[] args;
    private static String sql;
    private static Connection connection;
    private static PreparedStatement preparedStatement = null;

    public SqlExecuteHandler(Method method, Object[] args, String sql, Connection connection) {
        SqlExecuteHandler.method = method;
        SqlExecuteHandler.args = args;
        SqlExecuteHandler.sql = sql;
        SqlExecuteHandler.connection = connection;
    }

    //查询Sql解析
    public PreparedStatement selectSql() throws Exception {
        if (hasArgs()) return connection.prepareStatement(sql);
        return preparedStatement;
    }

    //其他Sql解析
    public PreparedStatement executeSql() throws Exception {
        Parameter[] parameters = method.getParameters();
        //判断参数是否为对象
        if (parameters.length == 1 && !isJavaClass(parameters[0].getType())) {
            Object obj = args[0];
            //获得所有#{}占位符中参数
            List<String> paramNames = new ArrayList<>();
            do {
                paramNames.add(sql.substring(sql.indexOf("#{") + 2, sql.indexOf("}")));
                sql = sql.substring(sql.indexOf("}") + 1);
            } while (sql.contains("#{"));

            //将占位符#{}替换为?占位符
            for (String paramName : paramNames) {
                sql = sql.replace("#{" + paramName + "}", "?");
            }

            connection.prepareStatement(sql);
            //给占位符赋值
            for (int i = 0; i < paramNames.size(); i++) {
                String methodName = "get" + StringUtil.firstToUpperCase(paramNames.get(i));
                Method objMethod = obj.getClass().getMethod(methodName);
                preparedStatement.setObject(i + 1, objMethod.invoke(obj));
            }
        } else {
            hasArgs();
        }
        return preparedStatement;
    }


    //判断是否是java类
    private static boolean isJavaClass(Class<?> clz) {
        return clz != null && clz.getClassLoader() == null;
    }

    //判断sql语句是否含有占位符
    private static boolean hasArgs() throws SQLException {
        //如果sql中不含占位符，则直接返回
        if (!sql.contains("#")) {
            return true;
        }
        //获取方法参数
        Parameter[] parameters = method.getParameters();
        //若参数中有参数没有使用@Param注解，则抛出异常
        for (int i = 0; i < parameters.length; i++) {
            if (parameters[i].getAnnotation(Param.class) == null) {
                throw new RuntimeException("参数" + i + "没有使用@Param注解");
            }
        }
        //将参数名替换为?占位符，这里仅针对#{}
        for (Parameter parameter : parameters) {
            //获取参数名
            String paramName = parameter.getAnnotation(Param.class).value();
            //替换参数名
            sql = sql.replace("#{" + paramName + "}", "?");
        }
        //执行sql
        preparedStatement = connection.prepareStatement(sql);
        for (int i = 0; i < args.length; i++) {
            preparedStatement.setObject(i + 1, args[i]);
        }
        return false;
    }
}
